import {
  Injectable,
  NotFoundException,
  ConflictException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like } from 'typeorm';
import { User } from '../entities/user.entity';
import { Sku } from '../entities/sku.entity';

interface UserWhere {
  name?: any;
  phone?: any;
  isDeleted?: boolean;
}

interface CreateUserDto {
  name: string;
  phone: string;
  skuIds?: number[];
}

interface UpdateUserDto {
  name?: string;
  phone?: string;
  skuIds?: number[];
}

interface FindAllQuery {
  name?: string;
  phone?: string;
  skuId?: number;
  page?: number;
  size?: number;
}

interface FindAllResponse {
  data: User[];
  total: number;
}

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private userRepository: Repository<User>,
    @InjectRepository(Sku)
    private skuRepository: Repository<Sku>,
  ) {}

  async create(createUserDto: CreateUserDto): Promise<User> {
    // 检查手机号是否已存在
    const existingUser = await this.userRepository.findOne({
      where: { phone: createUserDto.phone },
    });

    if (existingUser) {
      throw new ConflictException('该手机号已被注册');
    }

    const newUser = this.userRepository.create({
      name: createUserDto.name,
      phone: createUserDto.phone,
    });

    if (createUserDto.skuIds && createUserDto.skuIds.length > 0) {
      const skus = await this.skuRepository.findByIds(createUserDto.skuIds);
      if (skus.length !== createUserDto.skuIds.length) {
        throw new NotFoundException('Some SKUs were not found');
      }
      newUser.skus = skus;
    }

    return await this.userRepository.save(newUser);
  }

  async update(id: number, updateUserDto: UpdateUserDto): Promise<User> {
    const existingUser = await this.userRepository.findOne({
      where: { id },
    });

    if (!existingUser) {
      throw new NotFoundException(`User with ID ${id} not found`);
    }

    // 如果更新了手机号，需要检查是否与其他用户重复
    if (updateUserDto.phone && updateUserDto.phone !== existingUser.phone) {
      const phoneExists = await this.userRepository.findOne({
        where: { phone: updateUserDto.phone },
      });

      if (phoneExists) {
        throw new ConflictException('该手机号已被注册');
      }
    }

    // 更新用户基本信息
    Object.assign(existingUser, {
      name: updateUserDto.name,
      phone: updateUserDto.phone,
    });

    // 如果传入了skuIds，更新用户的SKU关联
    if (updateUserDto.skuIds) {
      const skus = await this.skuRepository.findByIds(updateUserDto.skuIds);
      if (skus.length !== updateUserDto.skuIds.length) {
        throw new NotFoundException('Some SKUs were not found');
      }
      existingUser.skus = skus;
    }

    return await this.userRepository.save(existingUser);
  }

  async findAll(query: FindAllQuery): Promise<FindAllResponse> {
    const where: UserWhere = {
      isDeleted: false,
    };
    const page = query.page || 1;
    const size = query.size || 10;

    if (query.name) {
      where.name = Like(`%${query.name}%`);
    }
    if (query.phone) {
      where.phone = Like(`%${query.phone}%`);
    }

    const queryBuilder = this.userRepository
      .createQueryBuilder('user')
      .leftJoinAndSelect('user.skus', 'sku')
      .where('user.isDeleted = :isDeleted', { isDeleted: false });

    if (query.skuId) {
      queryBuilder.innerJoin(
        'user.skus',
        'filterSku',
        'filterSku.id = :skuId',
        { skuId: query.skuId },
      );
    }

    if (query.name) {
      queryBuilder.andWhere('user.name LIKE :name', {
        name: `%${query.name}%`,
      });
    }
    if (query.phone) {
      queryBuilder.andWhere('user.phone LIKE :phone', {
        phone: `%${query.phone}%`,
      });
    }

    const [users, total] = await queryBuilder
      .skip((page - 1) * size)
      .take(size)
      .getManyAndCount();

    return {
      data: users,
      total,
    };
  }

  async findOne(id: number): Promise<User> {
    const user = await this.userRepository.findOne({
      where: { id, isDeleted: false },
      relations: ['skus'],
    });
    if (!user) {
      throw new NotFoundException(`User with ID ${id} not found`);
    }
    return user;
  }

  async remove(id: number): Promise<void> {
    const user = await this.findOne(id);
    user.isDeleted = true;
    await this.userRepository.save(user);
  }
}
